package com.corundumstudio.socketio.protocol;

import com.corundumstudio.socketio.namespace.Namespace;
import io.netty.buffer.ByteBuf;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * An encoded packet can be UTF-8 string or binary data. The packet encoding format for a string is as follows
 * Created by alex on 15-7-20.
 */
public class Packet implements Serializable {

    private static final long serialVersionUID = 4560159536486711426L;

    private PacketType type;
    private PacketType subType;
    private Long ackId;
    private String name;
    private String nsp = Namespace.DEFAULT_NAME;
    private Object data;

    private ByteBuf dataSource;
    private int attachmentCount;
    private List<ByteBuf> attachments = Collections.emptyList();

    protected Packet() {
    }

    public Packet(PacketType type) {
        super();
        this.type = type;
    }

    public PacketType getSubType() {
        return subType;
    }

    public void setSubType(PacketType subType) {
        this.subType = subType;
    }

    public PacketType getType() {
        return type;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public <T> T getData() {
        return (T)data;
    }

    public void setNsp(String endpoint) {
        this.nsp = endpoint;
    }

    public String getNsp() {
        return nsp;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getAckId() {
        return ackId;
    }

    public void setAckId(Long ackId) {
        this.ackId = ackId;
    }

    public boolean isAckRequested() {
        return getAckId() != null;
    }

    public void initAttachments(int attachmentsCount) {
        this.attachmentCount = attachmentsCount;
        this.attachments = new ArrayList<ByteBuf>(attachmentsCount);
    }

    public void addAttachment(ByteBuf attachment) {
        if (this.attachments.size() < attachmentCount) {
            this.attachments.add(attachment);
        }
    }

    public List<ByteBuf> getAttachments() {
        return attachments;
    }

    public boolean hasAttachments() {
        return attachmentCount != 0;
    }

    public boolean isAttachmentsLoaded() {
        return this.attachments.size() == attachmentCount;
    }

    public ByteBuf getDataSource() {
        return dataSource;
    }

    public void setDataSource(ByteBuf dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public String toString() {
        return "Packet [type=" + type + ", ackId=" + ackId + "]";
    }
}
